package netty5.webSocket;

import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.handler.codec.http.DefaultFullHttpResponse;
import io.netty.handler.codec.http.FullHttpRequest;
import io.netty.handler.codec.http.HttpResponseStatus;
import io.netty.handler.codec.http.HttpVersion;
import io.netty.handler.codec.http.websocketx.*;
import io.netty.util.concurrent.EventExecutor;

import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.util.Date;
import java.util.concurrent.TimeUnit;

/**
 * Created by GanJc on 2015/11/22.
 */
public class WebSocketServerHandler extends SimpleChannelInboundHandler<Object> {

    private WebSocketServerHandshaker handShaker ;

    @Override
    protected void messageReceived(ChannelHandlerContext ctx, Object o) throws Exception {
        System.out.println(o);

        InetSocketAddress socketAddress = (InetSocketAddress) ctx.channel().remoteAddress();
        InetSocketAddress localAddress = (InetSocketAddress) ctx.channel().localAddress();
        System.out.println(socketAddress);
        System.out.println(localAddress);
        EventExecutor executor = ctx.executor();
        executor.scheduleAtFixedRate(new Runnable() {
            @Override
            public void run() {
                System.out.println("哈哈哈哈哈哈");
            }
        },0,5,TimeUnit.SECONDS);
        System.out.println(executor);

        //http接入
        if(o instanceof FullHttpRequest){
            System.out.println("http接入");
            handlerHttpRequest(ctx, (FullHttpRequest) o);
        }
        //webSocket接入
        if(o instanceof WebSocketFrame){
            System.out.println("webSocket接入");
            handlerWebSocketFrame(ctx, (WebSocketFrame) o);
        }

    }

    @Override
    public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
        ctx.flush();
    }

    private void handlerWebSocketFrame(ChannelHandlerContext ctx, WebSocketFrame frame) {
        //判断是否是关闭指令
        if(frame instanceof CloseWebSocketFrame){
            handShaker.close(ctx.channel(),(CloseWebSocketFrame)frame.retain());
            return;
        }
        //判断是否ping消息
        if(frame instanceof PingWebSocketFrame){
            ctx.channel().write(new PongWebSocketFrame(frame.content().retain()));
            return;
        }
        //只支持文本消息 不支持二进制消息
        if(!(frame instanceof TextWebSocketFrame)){
            throw new UnsupportedOperationException("仅支持文本消息");
        }

        //返回应答消息
        String req = ((TextWebSocketFrame) frame).text();
        System.out.println("收到消息:" + req);

        ctx.channel().write(
          new TextWebSocketFrame(req+"欢迎使用webSocket服务，现在时间是:" + new Date().toString())
        );

    }

    private void handlerHttpRequest(ChannelHandlerContext ctx, FullHttpRequest req) {
        //如果解码失败 返回http异常
        if(!req.decoderResult().isSuccess()
                || !"websocket".equals(req.headers().get("Upgrade"))){
            sendHttpResponse(ctx,req,new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.BAD_REQUEST));
            return;
        }
        WebSocketServerHandshakerFactory factory = new WebSocketServerHandshakerFactory(
                "ws://127.0.0.1:8888/websocket",null,true
        );
        handShaker = factory.newHandshaker(req);
        if(handShaker==null){
            System.out.println("sendUnsupportedVersionResponse");
            factory.sendUnsupportedVersionResponse(ctx.channel());
        }else {
            handShaker.handshake(ctx.channel(),req);
            System.out.println("handshake");
        }
    }

    private void sendHttpResponse(ChannelHandlerContext ctx, FullHttpRequest req, DefaultFullHttpResponse response) {
        System.out.println("sendHttpResponse--------");
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        System.out.println(cause.getMessage());
        ctx.close();
    }

    @Override
    public void channelRegistered(ChannelHandlerContext ctx) throws Exception {
        super.channelRegistered(ctx);
        System.out.println("一个客户端注册上来了!");
    }
}
